//
//  PYCPersonTableController.m
//  PinyinContacts
//
//  Created by Xiaoping Zhang on 2/15/10.
//  Copyright 2010 Filters, Inc. All rights reserved.
//

#import "PYCContactTableController.h"
#import "PYCHzpy.h"
#import "PYCProgressViewController.h"
#import "PYCHZInspectorController.h"
#import "PYCHZWithMultiPYsInspectorController.h"

#import <AddressBook/ABGlobals.h>
#import <AddressBook/ABAddressBook.h>
#import <AddressBook/ABGroup.h>
#import <AddressBook/ABPerson.h>

static NSString *kFirstNameColumnIdentifier = @"firstNameColumn";
static NSString *kLastNameColumnIdentifier = @"lastNameColumn";
static NSString *kPhoneticFirstNameColumnIdentifier = @"phoneticFirstNameColumn";
static NSString *kPhoneticLastNameColumnIdentifier = @"phoneticLastNameColumn";

static NSString *kGetPhoneticsToolbarItemIdentifier = @"getPhoneticsToolbarItem";

@interface PYCContactTableController ()

- (void)initHZPYDatabase;
- (void)addRecords;
- (NSArray *)fetchEntity:(NSString *)character;
- (void) updateContactPhonetics:(ABPerson *)contact from:(NSString *)keyForPhoneticsFromProperty to:(NSString *)keyForPhoneticsToProperty;
- (void) updateContacts;
- (void) updateProgress:(id)progressValue;

@end

@implementation PYCContactTableController

@synthesize contacts;

- (void)awakeFromNib
{
	isInProgressOfGettingPhonetics = NO;
	
	[self initHZPYDatabase];
}

- (void)dealloc
{
	[super dealloc];
	
	[hzPYDBContext release];
}

- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{
	ABPerson *person = [[self contacts] objectAtIndex:rowIndex];
	
	if (!person)
		return nil;
	
	id columnIdentifier = [aTableColumn identifier];
	if (!columnIdentifier || ![columnIdentifier isKindOfClass:[NSString class]])
	{
		return nil;
	}
	
	NSString *columnIdentifierString = (NSString *)columnIdentifier;
	id value = nil;
	
	if ([columnIdentifierString isEqualToString:kFirstNameColumnIdentifier])
	{
		value = [person valueForProperty:kABFirstNameProperty];
	}
	else if ([columnIdentifierString isEqualToString:kLastNameColumnIdentifier])
	{
		value = [person valueForProperty:kABLastNameProperty];
	}
	else if ([columnIdentifierString isEqualToString:kPhoneticFirstNameColumnIdentifier])
	{
		value = [person valueForProperty:kABFirstNamePhoneticProperty];
	}
	else if ([columnIdentifierString isEqualToString:kPhoneticLastNameColumnIdentifier])
	{
		value = [person valueForProperty:kABLastNamePhoneticProperty];
	}

	return value;
}

- (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
	if (!object || ![object isKindOfClass:[NSString class]])
		return;
	
	NSString *stringObject = (NSString *)object;
	if ([stringObject length] == 0 || [stringObject isEqualToString:@""])
		return;
	
	ABPerson *person = [[self contacts] objectAtIndex:row];
	if (!person)
		return;
	
	id columnIdentifier = [tableColumn identifier];
	if (!columnIdentifier || ![columnIdentifier isKindOfClass:[NSString class]])
	{
		return;
	}
	
	NSString *columnIdentifierString = (NSString *)columnIdentifier;
	
	if ([columnIdentifierString isEqualToString:kFirstNameColumnIdentifier])
	{
		[person setValue:stringObject forProperty:kABFirstNameProperty];
	}
	else if ([columnIdentifierString isEqualToString:kLastNameColumnIdentifier])
	{
		[person setValue:stringObject forProperty:kABLastNameProperty];
	}
	else if ([columnIdentifierString isEqualToString:kPhoneticFirstNameColumnIdentifier])
	{
		[person setValue:stringObject forProperty:kABFirstNamePhoneticProperty];
	}
	else if ([columnIdentifierString isEqualToString:kPhoneticLastNameColumnIdentifier])
	{
		[person setValue:stringObject forProperty:kABLastNamePhoneticProperty];
	}
	
	[[ABAddressBook sharedAddressBook] save];
	
	return;
}

- (int)numberOfRowsInTableView:(NSTableView *)aTableView
{
    return [[self contacts] count];
}

- (void)initHZPYDatabase
{
	NSError *error;

	NSString *bundleResourcePath = [[NSBundle mainBundle] resourcePath];
	NSString *hzPYDatabasePath = [bundleResourcePath stringByAppendingString:@"/hzpy.sqlite"];
	NSURL *hzPYDatabaseURL = [NSURL fileURLWithPath:hzPYDatabasePath];
	
	NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
	// Establish the persistent store coordinator
	NSPersistentStoreCoordinator *persistentStoreCoordinator =
								[[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: managedObjectModel];
		
	if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType 
												  configuration:nil URL:hzPYDatabaseURL options:nil error:&error])
	{
		NSLog( @"Error: %@", [error localizedDescription]);	
	}
	else
	{ 
		// Create the context and assign the coordinator
		hzPYDBContext =	[[NSManagedObjectContext alloc] init];
		[hzPYDBContext setPersistentStoreCoordinator:persistentStoreCoordinator];
	}
	
	[persistentStoreCoordinator release] ;
}

- (void) updateContactPhonetics:(ABPerson *)contact from:(NSString *)keyForPhoneticsFromProperty to:(NSString *)keyForPhoneticsToProperty
{
	if (!contact || 
		!keyForPhoneticsFromProperty ||
		!keyForPhoneticsToProperty)
		return;
	
	NSString *phoneticsFrom = [contact valueForProperty:keyForPhoneticsFromProperty];
	if (!phoneticsFrom || [phoneticsFrom isEqualToString:@""])
		return;

// Skip these three lines.
//	NSString *phoneticsTo = [contact valueForProperty:keyForPhoneticsToProperty];
	// If the phonetics field is not empty, skip this.
//	if (phoneticsTo && ![phoneticsTo isEqualToString:@""])
//		return;
	
	NSUInteger countOfCharacters = [phoneticsFrom length];
	if (countOfCharacters == 0)
		return;
	
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	
	NSRange rangeOfCharacters = NSMakeRange(0, countOfCharacters);

	unichar *phoneticsFromCharacterBuffer = (unichar *)malloc(sizeof(unichar) * countOfCharacters);
	NSMutableString *resultPhoneticsString = [NSMutableString string];
	
	[phoneticsFrom getCharacters:phoneticsFromCharacterBuffer range:rangeOfCharacters];
	
	bool hasContinousPreviousPhonetic = NO;
	
	for (NSUInteger index = 0; index < countOfCharacters; ++index)
	{
		unichar currentCharacter = phoneticsFromCharacterBuffer[index];
		
		NSString *currentCharacterString = [NSString stringWithFormat:@"%C", currentCharacter];
		NSArray *characterPhonetics = [self fetchEntity:currentCharacterString];
		
		if (!characterPhonetics || [characterPhonetics count] == 0)
		{
			hasContinousPreviousPhonetic = NO;
			[resultPhoneticsString appendFormat:@"%C", currentCharacter]; 
		}
		else
		{
			if (hasContinousPreviousPhonetic)
			{
				[resultPhoneticsString appendString:@"-"];
			}
			else 
			{
				hasContinousPreviousPhonetic = YES;
			}
			
			// always get the first one
			PYCHzpy *hzpy = [characterPhonetics objectAtIndex:0];
			NSString *phoneticString = [hzpy pinyin];
			
			// Drop the accent sign at the end of each pinyin
			NSRange effectivePhoneticRange = NSMakeRange(0, [phoneticString length] - 1);
			NSString *effectivePhoneticString = [phoneticString substringWithRange:effectivePhoneticRange];
			
			[resultPhoneticsString appendString:[effectivePhoneticString capitalizedString]];
		}
	}
	
	[contact setValue:resultPhoneticsString forProperty:keyForPhoneticsToProperty];
	free(phoneticsFromCharacterBuffer);
	
	[pool release];
}

- (void) updateProgress:(id)progressValue
{
	if (!progressValue || ![progressValue isKindOfClass:[NSNumber class]])
		return;
	
	[progressViewController setProgress:[progressValue doubleValue]];
	
	NSUInteger countOfContacts = [[self contacts] count];
	
	if (countOfContacts == [progressValue unsignedIntValue])
	{
		[progressViewController closeProgressSheet];
		[progressViewController release];
		progressViewController = nil;
		
		[[ABAddressBook sharedAddressBook] save];
		isInProgressOfGettingPhonetics = NO;
		[tableView reloadData];
	}
}

- (void) updateContacts
{
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	
	NSUInteger currentIndex = 0;
	NSUInteger countOfContacts = [[self contacts] count];

	for (ABPerson *person in [self contacts])
	{
		[self updateContactPhonetics:person from:kABFirstNameProperty to:kABFirstNamePhoneticProperty];
		[self updateContactPhonetics:person from:kABLastNameProperty to:kABLastNamePhoneticProperty];
		
		[self performSelectorOnMainThread:@selector(updateProgress:) withObject:[NSNumber numberWithUnsignedInt:currentIndex] waitUntilDone:YES];
		
		++currentIndex;
	}
	
	[self performSelectorOnMainThread:@selector(updateProgress:) withObject:[NSNumber numberWithUnsignedInt:countOfContacts] waitUntilDone:YES];
	
	[pool release];
}

- (IBAction) getPhonetics:(id)sender
{
	NSUInteger countOfContacts = [[self contacts] count];
	
	if (countOfContacts == 0)
		return;
	
	isInProgressOfGettingPhonetics = YES;
	
	progressViewController = [[PYCProgressViewController alloc] init];
	[progressViewController setMaxValue:countOfContacts];
	
	[NSApp beginSheet:[[progressViewController view] window]
	   modalForWindow:mainWindow
		modalDelegate:progressViewController
	   didEndSelector:nil
		  contextInfo:nil];

	[NSThread detachNewThreadSelector:@selector(updateContacts) toTarget:self withObject:nil];
}

- (IBAction) inspectCharacters:(id)sender
{
	inspectorController = [[PYCHZInspectorController alloc] initWithObjectContext:hzPYDBContext];
	
	[NSApp beginSheet:[inspectorController window]
	   modalForWindow:mainWindow
		modalDelegate:self
	   didEndSelector:@selector(inspectorSheetDidEnd:returnCode:contextInfo:)
		  contextInfo:nil];
}

- (IBAction) inspectCharactersWithMultiPYs:(id)sender
{
	hzWithMultiPYsInspectorController = [[PYCHZWithMultiPYsInspectorController alloc] initWithObjectContext:hzPYDBContext];
	
	[NSApp beginSheet:[hzWithMultiPYsInspectorController window]
	   modalForWindow:mainWindow
		modalDelegate:self
	   didEndSelector:@selector(hzWithMultiPYsInspectorSheetDidEnd:returnCode:contextInfo:)
		  contextInfo:nil];
}

- (void)inspectorSheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
{
	[inspectorController release];
	inspectorController = nil;
}

- (void)hzWithMultiPYsInspectorSheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
{
	[hzWithMultiPYsInspectorController release];
	hzWithMultiPYsInspectorController = nil;
}

-(BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem
{
	id itemIdentifier = [toolbarItem itemIdentifier];
	
	if (!itemIdentifier || ![itemIdentifier isKindOfClass:[NSString class]])
		return YES;
	
	NSString *itemIdentifierString = (NSString *)itemIdentifier;
	
	if ([itemIdentifierString isEqualToString:kGetPhoneticsToolbarItemIdentifier])
	{
		return [contacts count] > 0 && !isInProgressOfGettingPhonetics;
	}
	
    return YES;	
}

- (void)addRecords
{
//	if (!hzPYDBContext)
//		return;
//	
//	PYCHzpy *record = (PYCHzpy *)[NSEntityDescription insertNewObjectForEntityForName:@"hzpy" inManagedObjectContext:hzPYDBContext];
//	
//	if (!record)
//		return;
//
//	record.hanzi = @"程";
//	record.pinyin = @"cheng2";
//
//	NSError *error;
//	
//	if (![hzPYDBContext save:&error])
//	{
//		NSLog(@"Error while saving: %@", [error localizedDescription]);
//	}
}

- (NSArray *)fetchEntity:(NSString *)character
{
	if (!hzPYDBContext)
		return nil;
	
	NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"hzpy" inManagedObjectContext:hzPYDBContext]; 
	NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease]; 
	[request setEntity:entityDescription];
	
	// Set example predicate and sort orderings... NSNumber *minimumSalary = ...; 
	NSPredicate *predicate = [NSPredicate predicateWithFormat:@"hanzi=%@", character];
	[request setPredicate:predicate];
	
	// Sort by priority
	NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"priority" ascending:NO];
	[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]]; [sortDescriptor release];
	
	NSError *error = nil; 
	NSArray *array = [hzPYDBContext executeFetchRequest:request error:&error]; 
	
	if (array == nil) 
	{
		// Deal with error...
	}
	
	return array;
}

@end
